package com.thornbird.vehiclerecycling.config;

import com.thornbird.vehiclerecycling.model.record.UserRecord;
import com.thornbird.vehiclerecycling.util.JsonUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class HttpLogger {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpLogger.class);

    @Pointcut("execution(public * com.thornbird.vehiclerecycling.controller..*.*(..))")
    public void log() {}

    @Before("log()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpSession session = request.getSession();
        UserRecord userRecord = (UserRecord) session.getAttribute(OAuth2LoginConfig.CURRENT_USER);
        String parameters = JsonUtil.toJsonString(getParameterMap(request));
        String classMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
        String args = Arrays.toString(joinPoint.getArgs());
        String content = String.format("uri=%s, method=%s, user=%s, parameters=%s, classMethod=%s, args=%s",
                request.getRequestURI(), request.getMethod(), userRecord == null ? null : userRecord.getFullName(),
                parameters, classMethod, args);
        LOGGER.info("REQUEST: " + content);
    }

    @AfterReturning(returning = "result", pointcut = "log()")
    public void doAfterReturning(Object result) {
        LOGGER.info("RESPONSE : " + result);
    }

    private Map<String, Object> getParameterMap(HttpServletRequest request) {
        Map<String, Object> parameterMap = null;
        if (request == null) {
            return parameterMap;
        }

        Enumeration<String> enumeration = request.getParameterNames();
        parameterMap = new HashMap<>();
        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            String value = request.getParameter(key);
            parameterMap.put(key, value);
        }
        return parameterMap;
    }

}
